package com.block.storage.service.oss;

import cn.hutool.core.collection.CollUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.GenericRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.block.storage.config.OssAliConfig;
import com.block.storage.model.OssAuthInfoParam;
import com.block.storage.model.dto.OSSAuthInfoDTO;
import com.block.storage.service.IOssService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;

@Service
public class OssAliService implements IOssService {

    @Autowired
    OssAliConfig ossAliConfig;

    @Override
    public boolean copyObjectKey(String sourceBucketName, String sourceObjectKey, String destinationBucketName, String destinationKey, OssAuthInfoParam ossAuthInfoParam) throws ClientException {
        OSS ossClient = null;
        try {
            ossClient = getClient(ossAuthInfoParam);
            CopyObjectResult result = ossClient.copyObject(sourceBucketName, sourceObjectKey, destinationBucketName, destinationKey);
            return true;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 对请求地址进行授权
     * @param objectKey
     * @return
     */
    @Override
    public String authObjectUrl(String objectKey, OssAuthInfoParam ossAuthInfoParam) throws ClientException {
        OSS ossClient = null;
        try {
            ossClient = getClient(ossAuthInfoParam);
            // 设置签名URL过期时间，单位为毫秒。
            Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(ossAliConfig.getBucketName(), objectKey, expiration);
            return url.toString();
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 查看 上传的对象是否存在
     * @param objectKeyList
     * @return
     */
    @Override
    public boolean existObjectKey(List<String> objectKeyList, OssAuthInfoParam ossAuthInfoParam) throws ClientException {
        OSS ossClient = null;
        try {

            if (CollUtil.isEmpty(objectKeyList)){
                return false;
            }

            ossClient = getClient(ossAuthInfoParam);

            GenericRequest genericRequest = new GenericRequest();
            genericRequest.setBucketName(ossAliConfig.getBucketName());

            for (String objectKey: objectKeyList){
                genericRequest.setKey(objectKey);
                boolean exist = ossClient.doesObjectExist(genericRequest);
                if (!exist){
                    return false;
                }
            }
            return true;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 上传文件
     * @param fileKey
     * @param inputStream
     */
    @Override
    public void uploadFile(String fileKey, InputStream inputStream, OssAuthInfoParam ossAuthInfoParam) throws ClientException {

        OSS ossClient = null;
        try {
            ossClient = getClient(ossAuthInfoParam);

            PutObjectRequest putObjectRequest = new PutObjectRequest(ossAliConfig.getBucketName(), fileKey, inputStream);

            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 获取客户端
     * @return
     */
    public OSS getClient(OssAuthInfoParam ossAuthInfoParam) throws ClientException {
        OSSAuthInfoDTO authParam = getAuthParam(ossAuthInfoParam);
        OSS ossClient = new OSSClientBuilder()
                .build(
                        authParam.getEndpoint(),
                        authParam.getAccessKeyId(),
                        authParam.getAccessKeySecret(),
                        authParam.getSecurityToken()
                );
        return ossClient;
    }

    /**
     * 获取授权信息
     * @return
     */
    @Override
    public OSSAuthInfoDTO getAuthParam(OssAuthInfoParam ossAuthInfoParam) throws ClientException {

        //构建一个阿里云客户端，用于发起请求。
        //设置调用者（RAM用户或RAM角色）的AccessKey ID和AccessKey Secret。
        DefaultProfile profile = DefaultProfile.getProfile(ossAuthInfoParam.getRegionId(), ossAliConfig.getAccessKey(), ossAliConfig.getAccessSecret());
        IAcsClient client = new DefaultAcsClient(profile);

        //构造请求，设置参数。
        AssumeRoleRequest request = new AssumeRoleRequest();
        request.setSysRegionId(ossAuthInfoParam.getRegionId());
        request.setRoleArn(ossAliConfig.getRoleArn());
        request.setRoleSessionName(ossAliConfig.getRoleSessionName());
        request.setDurationSeconds(ossAliConfig.getDuration());
//        request.setPolicy(ossAliConfig.getPolicy());

        //发起请求，并得到响应。
        AssumeRoleResponse response = client.getAcsResponse(request);
        AssumeRoleResponse.Credentials credentials = response.getCredentials();

        OSSAuthInfoDTO ossAuthInfoDTO = new OSSAuthInfoDTO();
        ossAuthInfoDTO.setExpiration(credentials.getExpiration());
        ossAuthInfoDTO.setAccessKeyId(credentials.getAccessKeyId());
        ossAuthInfoDTO.setAccessKeySecret(credentials.getAccessKeySecret());
        ossAuthInfoDTO.setSecurityToken(credentials.getSecurityToken());

        ossAuthInfoDTO.setBucketName(ossAuthInfoParam.getBucketName());
        ossAuthInfoDTO.setEndpoint(ossAuthInfoParam.getEndpoint());

        return ossAuthInfoDTO;

    }

}
